package com.nulldev.util.security.encryptAPI.streams;

import java.io.IOException;
import java.io.InputStream;

import com.nulldev.util.VariableAPI.MathUtil;
import com.nulldev.util.security.encryptAPI.Encryptor;

public class EncryptAPIInputStream extends InputStream {

	private final Encryptor enc;
	private final InputStream is;

	public EncryptAPIInputStream(final InputStream original, final Encryptor enc) {
		if (enc == null)
			throw new NullPointerException("enc == null!");
		if (original == null)
			throw new NullPointerException("is == null");
		this.enc = enc;
		this.is = original;
	}

	@Override
	public int read() throws IOException {
		throw new UnsupportedOperationException("Cannot read indiviual bytes!");
	}

	@Override
	public int read(byte[] b) throws IOException {
		final byte[] l = new byte[4];
		final int __r = this.is.read(l);
		if (__r < 0)
			return -1;
		final int len = MathUtil.getInt(l, 0);
		if (len <= 0)
			throw new IllegalStateException("len <= 0!");
		final byte[] p = new byte[len];
		final int _r = this.is.read(p);
		if (_r < 0)
			return -1;
		System.arraycopy(this.enc.decryptToBytes(p), 0, b, 0, b.length);
		return _r + __r;
	}

	@Override
	public int read(byte[] b, int off, int len) throws IOException {
		return this.read(b);
	}

	@Override
	public void close() throws IOException {
		this.is.close();
	}

	@Override
	public int available() throws IOException {
		return this.is.available();
	}

	@Override
	public boolean markSupported() {
		return this.is.markSupported();
	}

	@Override
	public synchronized void reset() throws IOException {
		this.is.reset();
	}

	@Override
	public synchronized void mark(final int readlimit) {
		this.is.mark(readlimit);
	}
}
